﻿/*
 * Created by SharpDevelop.
 * User: mac
 * Date: 20.07.2006
 * Time: 10:48
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Windows.Forms;
using TagTool.Core;
using TagTool.Devices;
using TagTool.Devices.Midi;
using TagTool.GraphicTypes;

namespace TagTool.Nodes.Devices
{
    /**
     * This node type makes Midi access for tagtool networks available.
     */
    public class MidiNoteNode : BaseNode
    {
        private MidiInputDevice midi;
        static Form f = new Form();

        private InputSlot port;
        double dPort;

        private InputSlot notes;
        
        private OutputSlot note;
        private OutputSlot velocity;

        /**
         * Constructor.
         */
        public MidiNoteNode() : base()
        {
            port = new InputSlot(this, "Port", 0.0);
            port.ParseCallback = ParseHelper.ParseDouble;
            dPort = 0.0;
            
            notes = new InputSlot(this, "Note range", new Range());
            notes.ParseCallback = Range.Parse;

            velocity = new OutputSlot(this, "Velocity", typeof(double));
            note = new OutputSlot(this, "Note", typeof(double));
			note.Value = 0.0;
			
            IntPtr x = f.Handle;
            
            midi = (MidiInputDevice)MidiManager.Instance.GetDevice(Convert.ToInt32((double)port.Value));
            
            if (midi != null)
            {
	            //midi.NoteOnEvent += new NoteOnEventHandler(OnNoteOnEvent);
	            midi.NoteOffEvent += new NoteOffEventHandler(OnNoteOffEvent);
	            if (!midi.Connected)
	            {
	            	midi.Connect();
	            }
	            Name = "Midi Note (present)";
            }
            else
            {
            	Name = "Midi Note (not present)";
            }
            
            velocity.Value = 0.0;
        }

        ~MidiNoteNode()
        {
            if (midi != null)
            {
            	midi.Disconnect();
            }
        }

        public override void Update(Object sender)
        { // do nothing to update

            if (dPort != (double)port.Value)
            {
            	if (midi != null)
            	{
                	midi.Disconnect();
                	//midi.NoteOnEvent -= new NoteOnEventHandler(OnNoteOnEvent);
                	midi.NoteOffEvent -= new NoteOffEventHandler(OnNoteOffEvent);
            	}
                midi = (MidiInputDevice)MidiManager.Instance.GetDevice(Convert.ToInt32((double)port.Value));
				
                if (midi != null)
            	{
	                midi.Connect();
	                //midi.NoteOnEvent += new NoteOnEventHandler(OnNoteOnEvent);
	                midi.NoteOffEvent += new NoteOffEventHandler(OnNoteOffEvent);
	                Name = "Midi Note (present)";
                }
                else
                {
                	Name = "Midi Note (not present)";
                }
                
                dPort = (double)port.Value;
            }

        }

        [NodeAttribute(SlotType.Input, Show = true)]
        public InputSlot Port
        {
            get { return port; }
        }

        [NodeAttribute(SlotType.Input, Show = true)]
        public InputSlot Notes
        {
            get { return notes; }
        }
        
        [NodeAttribute(SlotType.Output, Show = true)]
        public OutputSlot Note
        {
            get { return note; }
        }

        [NodeAttribute(SlotType.Output, Show = true)]
        public OutputSlot Velocity
        {
            get { return velocity; }
        }
   
        private void OnNoteOnEvent(object sender, MidiDeviceEventArgs e)
        {
            f.Invoke(new NoteOnEventHandler(ParseNoteOnArgs), sender, e);
        }

        private void ParseNoteOnArgs(object sender, MidiDeviceEventArgs e)
        {
        	//Console.WriteLine("Note on");
            NoteOnMessage msg = (NoteOnMessage)e.ChannelMessage;
            if (((Range)notes.Value).IsInside((double)msg.Note))
            {
                velocity.Value = (double)msg.Velocity;
                note.Value = (double)msg.Note;
                if ((double)msg.Velocity > 0.0)

                CastTrigger();
            }
        }

        private void OnNoteOffEvent(object sender, MidiDeviceEventArgs e)
        {
            f.Invoke(new NoteOffEventHandler(ParseNoteOffArgs), sender, e);
        }

        private void ParseNoteOffArgs(object sender, MidiDeviceEventArgs e)
        {
        	
            NoteOffMessage msg = (NoteOffMessage)e.ChannelMessage;
            if (((Range)notes.Value).IsInside((double)msg.Note))
            {
                velocity.Value = 0.0;
                note.Value = (double)msg.Note;
                CastTrigger();
            }
        }
  
    }
}
